package org.example.trainTicketSystem.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.example.trainTicketSystem.DTO.GetScheduleDTO;
import org.example.trainTicketSystem.DTO.TicketDTO;
import org.example.trainTicketSystem.DTO.TrainScheduleDTO;
import org.example.trainTicketSystem.entity.Ticket;
import org.example.trainTicketSystem.entity.TrainSchedule;
import org.example.trainTicketSystem.service.TicketService;
import org.example.trainTicketSystem.service.TrainScheduleService;
import org.example.trainTicketSystem.utils.ResponseResult;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@RestController
@RequestMapping("/api/trains")
@RequiredArgsConstructor
public class TrainScheduleController {

    private final TrainScheduleService trainScheduleService;
    private final TicketService ticketService;

    @PostMapping()
    public ResponseResult<TrainSchedule> addSchedule(
            @Valid @RequestBody TrainScheduleDTO trainScheduleDTO,
            @RequestParam BigDecimal price,
            HttpServletRequest request) {

        // 权限验证
        Boolean isAdmin = (Boolean) request.getAttribute("isAdmin");
        if (!Boolean.TRUE.equals(isAdmin)) {
            log.warn("Unauthorized schedule addition attempt");
            return ResponseResult.fail("权限不足");
        }

        // 时间验证
        if (validateScheduleTime(trainScheduleDTO)) {
            log.warn("Invalid train schedule time: {}", trainScheduleDTO);
            return ResponseResult.fail("到达时间不得晚于出发时间");
        }

        // 创建车次
        TrainSchedule trainSchedule = new TrainSchedule(trainScheduleDTO);

        // 检查车次冲突
        if (checkScheduleConflict(trainSchedule)) {
            log.warn("Train schedule conflict detected: {}", trainScheduleDTO);
            return ResponseResult.fail("车次存在冲突");
        }

        try {
            // 保存车次
            if (trainScheduleService.save(trainSchedule)) {
                // 创建车票
                createTrainTickets(trainSchedule, price);

                log.info("Train schedule added successfully: {}", trainSchedule.getTrainNumber());
                return ResponseResult.success("车次添加成功", trainSchedule);
            } else {
                log.error("Failed to add train schedule: {}", trainScheduleDTO);
                return ResponseResult.fail("车次添加失败");
            }
        } catch (Exception e) {
            log.error("Error adding train schedule", e);
            return ResponseResult.fail("车次添加失败：" + e.getMessage());
        }
    }

    @GetMapping()
    public ResponseResult<Page<TrainSchedule>> getSchedule(
            @ParameterObject @ModelAttribute GetScheduleDTO getScheduleDTO,
            @RequestParam(defaultValue = "1") int page,
            @RequestParam(defaultValue = "10") int size) {

        try {
            Page<TrainSchedule> trainSchedules = trainScheduleService.selectTrainSchedule(getScheduleDTO, page, size);
            log.info("Train schedules retrieved successfully");
            return ResponseResult.success("车次获取成功", trainSchedules);
        } catch (Exception e) {
            log.error("Error retrieving train schedules", e);
            return ResponseResult.fail("车次获取失败");
        }
    }

    @GetMapping("/trainNumber")
    public ResponseResult<Page<TrainSchedule>> getScheduleByNumber(@PathVariable String trainNumber,
                                                                   @RequestParam(defaultValue = "1") int page,
                                                                   @RequestParam(defaultValue = "10") int size) {
        try {
            Page<TrainSchedule> trainSchedules = trainScheduleService.selectTrainScheduleByTrainNumber(trainNumber, page, size);
            log.info("Train schedules retrieved successfully");
            return ResponseResult.success("车次获取成功", trainSchedules);
        } catch (Exception e) {
            log.error("Error retrieving train schedules", e);
            return ResponseResult.fail("车次获取失败");
        }
    }

    @GetMapping("/all")
    public ResponseResult<Page<TrainSchedule>> getAllSchedule(@RequestParam(defaultValue = "1") int page,
                                                              @RequestParam(defaultValue = "10") int size) {
        return ResponseResult.success("车次获取成功",trainScheduleService.selectAllTrainSchedule(page,size));
    }

    @DeleteMapping()
    public ResponseResult<TrainSchedule> deleteSchedule(
            @RequestParam int trainId,
            HttpServletRequest request) {

        // 权限验证
        Boolean isAdmin = (Boolean) request.getAttribute("isAdmin");
        if (!Boolean.TRUE.equals(isAdmin)) {
            log.warn("Unauthorized schedule deletion attempt");
            return ResponseResult.fail("权限不足");
        }

        TrainSchedule trainSchedule = trainScheduleService.getById(trainId);
        if (trainSchedule == null) {
            log.warn("Attempt to delete non-existent train schedule: {}", trainId);
            return ResponseResult.fail("暂无此车次");
        }

        try {
            // 删除关联车票
            ticketService.deleteTicket(trainId);

            // 删除车次
            if (trainScheduleService.removeById(trainId)) {
                log.info("Train schedule deleted successfully: {}", trainId);
                return ResponseResult.success("删除该车次成功", trainSchedule);
            } else {
                log.error("Failed to delete train schedule: {}", trainId);
                return ResponseResult.fail("删除该车次失败");
            }
        } catch (Exception e) {
            log.error("Error deleting train schedule", e);
            return ResponseResult.fail("删除车次失败：" + e.getMessage());
        }
    }

    @PutMapping()
    @CacheEvict(value = "trains", allEntries = true)
    public ResponseResult<TrainSchedule> updateSchedule(
            @Valid @RequestBody TrainSchedule trainSchedule,
            HttpServletRequest request) {

        // 权限验证
        Boolean isAdmin = (Boolean) request.getAttribute("isAdmin");
        if (!Boolean.TRUE.equals(isAdmin)) {
            log.warn("Unauthorized schedule update attempt");
            return ResponseResult.fail("权限不足");
        }

        try {
            if (trainScheduleService.updateById(trainSchedule)) {
                log.info("Train schedule updated successfully: {}", trainSchedule.getTrainId());
                return ResponseResult.success("车次信息更新成功", trainSchedule);
            } else {
                log.error("Failed to update train schedule: {}", trainSchedule.getTrainId());
                return ResponseResult.fail("车次信息更新失败");
            }
        } catch (Exception e) {
            log.error("Error updating train schedule", e);
            return ResponseResult.fail("车次信息更新失败：" + e.getMessage());
        }
    }

    // 时间验证方法
    private boolean validateScheduleTime(TrainScheduleDTO trainScheduleDTO) {
        LocalDateTime departureTime = trainScheduleDTO.getDepartureTime();
        LocalDateTime arrivalTime = trainScheduleDTO.getArrivalTime();
        return arrivalTime.isBefore(departureTime);
    }

    // 车次冲突检查方法
    private boolean checkScheduleConflict(TrainSchedule newSchedule) {
        List<TrainSchedule> existingSchedules = trainScheduleService
                .selectTrainScheduleByTrainNumber(newSchedule.getTrainNumber(),1,10000).getRecords();

        return existingSchedules.stream().anyMatch(existingSchedule ->
                newSchedule.getDepartureTime().isBefore(existingSchedule.getArrivalTime()) ||
                        newSchedule.getArrivalTime().isAfter(existingSchedule.getArrivalTime())
        );
    }

    // 创建车票的方法
    private void createTrainTickets(TrainSchedule trainSchedule, BigDecimal price) {
        List<Ticket> tickets = new ArrayList<>();

        // 一等座
        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 10; j++) {
                tickets.add(new Ticket(new TicketDTO(
                        trainSchedule.getTrainId(),
                        (i + 1) + "号车厢",
                        (j + 1) + "号车座",
                        "一等座",
                        price.multiply(BigDecimal.valueOf(2)),
                        "AVAILABLE"
                )));
            }
        }

        // 二等座
        for (int i = 2; i < 6; i++) {
            for (int j = 0; j < 10; j++) {
                tickets.add(new Ticket(new TicketDTO(
                        trainSchedule.getTrainId(),
                        (i + 1) + "号车厢",
                        (j + 1) + "号车座",
                        "二等座",
                        price,
                        "AVAILABLE"
                )));
            }
        }

        // 批量保存车票
        ticketService.saveBatch(tickets);
    }
}